
package org.apli.haiam.controladores;

import com.apli.controladores.Aplinfo;
import com.apli.ejb.exceptions.ApliException;
import com.apli.ejb.exceptions.TipoMensajeError;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.apli.haiam.admin.entidades.UsuarioAdmin;
import org.apli.haiam.ejb.entidades.AdmAccion;
import org.apli.haiam.ejb.entidades.AdmDatosGlobales;
import org.apli.haiam.ejb.entidades.AdmMenu;
import org.apli.haiam.ejb.entidades.AdmSesion;
import org.apli.haiam.ejb.entidades.AdmSistema;
import org.apli.haiam.ejb.entidades.AdmUsuario;
import org.apli.haiam.ejb.interfaces.AdministradorLoginHaiam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Clase que implementa la interface
 * <code>{@link ec.gov.mdmq.admin.ejb.interfaces.AdministradorLoginDmq}</code>.
 * <H6>Soporte:HAIMA
 * <I>david_s_1086@hotmail.com,david.carranza@haiam.gob.ec</I></H6>
 * @author david Carranza
 * @version 1.0 30/07/2014
 */
@Stateless
public class AdministradorLoginBeanHaiam extends HaiamAbstractFacade<AdmUsuario> implements AdministradorLoginHaiam, Serializable {

    private static final long serialVersionUID = 1L;
    @PersistenceContext(unitName = "Admin-ejbPU")
    private EntityManager em;
    /**
     * Definicón de constanetes para cada acción
     */
    private static final String INICIAR_SESION = "Iniciar sesión";
    /**
     * Variable para registrar sucesos del sistema
     */
    private static final Logger log = LoggerFactory.getLogger(AdministradorLoginBeanHaiam.class);

    public AdministradorLoginBeanHaiam() {
    }

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    /**
     * Valida las credenciales para iniciar una sesión.
     *
     * @param username nombre de usuario en el sistema, normalmente debe ser la
     * del Directorio Activo
     * @param password contraseña del usuario, normalmente debe ser la del
     * Directorio Activo
     * @param ip la dirección IP del host cliente
     * @param sistema sistema desde el cual se inicia una sesión
     * @return el objeto usuario con todos los perfiles y datos
     * @throws Exception si existe un error
     */
    @Override
    public Object iniciarSesion(String username, String password, String ip, String host, AdmSistema sistema, AdmSistema sistemaPrincipal, String idSesion) throws Exception {
        String nombreMetodo = Thread.currentThread().getStackTrace()[1].getMethodName() + "(" + username + ", PWD," + ip + "," + sistema + "," + idSesion + ")";
        String password2 = Aplinfo.encriptarHash(password);
        if (sistema == null) {
            throw new ApliException(TipoMensajeError.SYSTEM_NULL);
        }
        AdmUsuario objUser = null;
        try {
            objUser = (AdmUsuario) getEntityManager().createQuery("Select T from AdmUsuario T where T.username=:usr and T.password=:pwd").setParameter("usr", username).setParameter("pwd", password2).getSingleResult();
            if (objUser.getEstado() != 1) {
                throw new ApliException(TipoMensajeError.USER_INACTIVO);
            }
        } catch (ApliException e) {
            log.error("{} {}", new Object[]{nombreMetodo, e});
            throw new ApliException(TipoMensajeError.USER_NO_REGISTERED, e);
        }
        UsuarioAdmin user = new UsuarioAdmin(objUser);
        user.setSistema(sistema);
        try {
            //Carga las acciones o permisos que tiene el usuario
            List<AdmAccion> o1 = getEntityManager().createQuery("Select distinct A.admAccionList from AdmUsuario T, in (T.admRolList) A where T = :u").setParameter("u", objUser).getResultList();
            Map<String, AdmAccion> permisos = new HashMap<>();

            for (AdmAccion admAccion : o1) {
                permisos.put(admAccion.getClave(), admAccion);
            }
            List<AdmMenu> menu = getMenuPorSistemaAsignados(sistemaPrincipal != null ? sistemaPrincipal : sistema);
// --        
            if (user.getUser().getAdmEmpleado() != null) {
                user.setNombreFull(user.getUser().getAdmEmpleado().getNombreFull());
                user.setIdInstitucion(user.getUser().getAdmEmpleado().getAdmInstitucion().getIdInstitucion());
                user.setNombreInstitucion(user.getUser().getAdmEmpleado().getAdmInstitucion().getNombre());
            } else {
                if (user.getUser().getAdmMedico() != null) {
                    user.setNombreFull(user.getUser().getAdmMedico().getAmeNombreFull());
                    user.setIdInstitucion(user.getUser().getAdmMedico().getAdmInstitucion().getIdInstitucion());
                    user.setNombreInstitucion(user.getUser().getAdmMedico().getAdmInstitucion().getNombre());
                }
            }

            user.setPermisosMap(permisos);
            menu = getListMenuPorPerfiles(menu, user);
            user.setMenu(menu);   /// utilizando el sistema


            user.setIp(ip);
            user.setHost(host);
            
// --       
            /**
             * grabar Auditoría
             */
            Object logObj = Aplinfo.cloneObjectEjb(objUser, false);
            String descripcion = "El usuario " + user.getNombreFull() + " inició una sesión en el sistema";

            grabarAuditoria(INICIAR_SESION, logObj, user, descripcion);
            /**
             * FIN -- grabar Auditoría
             */
            objUser.setFechaUltimoAcceso(getFechaDb());
            /**
             * Graba un token de autenticación
             */
            AdmSesion sesion = new AdmSesion(Aplinfo.generarUUID());
            sesion.setIp(user.getIp());
            sesion.setAdmSistema(sistema);
            sesion.setAdmUsuario(objUser);
            sesion.setFecha(getFechaDb());
            sesion.setEstado((short) 1);
            sesion.setSesion(idSesion);

            //sesion = getEntityManager().merge(sesion);
            getEntityManager().persist(sesion);
            user.setSesion(sesion);

            getEntityManager().merge(objUser);
            //getEntityManager().flush();
            return user;
        } catch (Exception e) {
            log.error("{} {}", new Object[]{nombreMetodo, e});
            throw new ApliException(TipoMensajeError.INICIAR_SESION, e);
        }
    }

    /**
     * Valida las credenciales para iniciar una sesión.
     *
     * @param ip la dirección IP del host cliente
     * @param sistema sistema desde el cual se inicia una sesión
     * * @param datosGlobales especificamente para este sistema las impresoras
     * registradas
     * @return el objeto usuario con todos los perfiles y datos
     * @throws Exception si existe un error
     */
    @Override
    public Object iniciarSesionToken(AdmSesion token, String ip, String host, AdmSistema sistema, AdmSistema sistemaPrincipal, List<AdmDatosGlobales> datosGlobales) throws Exception {
        if (sistema == null) {
            throw new ApliException(TipoMensajeError.SYSTEM_NULL);
        }
        AdmUsuario objUser = null;
        try {
            objUser = (AdmUsuario) getEntityManager().createQuery("Select T from AdmUsuario T where T.username=:usr").setParameter("usr", token.getAdmUsuario().getUsername()).getSingleResult();
            if (objUser.getEstado() == 0) {
                throw new ApliException(TipoMensajeError.USER_INACTIVO);
            }
        } catch (ApliException e) {
            throw new ApliException(TipoMensajeError.USER_NO_REGISTERED, e);
        }
        UsuarioAdmin user = new UsuarioAdmin(objUser);
        // si es usuario del DA, recupero la clave para poder validar en el directorio activo
        user.setSistema(sistema);
        try {
            //Carga las acciones o permisos que tiene el usuario
            List<AdmAccion> o1 = getEntityManager().createQuery("Select distinct A.admAccionList from AdmUsuario T, in (T.admRolList) A where T = :u").setParameter("u", objUser).getResultList();
            Map<String, AdmAccion> permisos = new HashMap<>();

            for (AdmAccion admAccion : o1) {
                permisos.put(admAccion.getClave(), admAccion);
            }
            List<AdmMenu> menu = getMenuPorSistemaAsignados(sistemaPrincipal != null ? sistemaPrincipal : sistema);
// --     
            user.setPermisosMap(permisos);
            menu = getListMenuPorPerfiles(menu, user);
            user.setMenu(menu);   /// utilizando el sistema
            if (user.getUser().getAdmEmpleado() != null) {
                user.setNombreFull(user.getUser().getAdmEmpleado().getNombreFull());
                user.setIdInstitucion(user.getUser().getAdmEmpleado().getAdmInstitucion().getIdInstitucion());
                user.setNombreInstitucion(user.getUser().getAdmEmpleado().getAdmInstitucion().getNombre());
            } else {
                if (user.getUser().getAdmMedico() != null) {
                    user.setNombreFull(user.getUser().getAdmMedico().getAmeNombreFull());
                    user.setIdInstitucion(user.getUser().getAdmMedico().getAdmInstitucion().getIdInstitucion());
                    user.setNombreInstitucion(user.getUser().getAdmMedico().getAdmInstitucion().getNombre());
                }
            }
            user.setIp(ip);
            user.setHost(host);
            user.setDatosGlobales(datosGlobales);
            // --             
            /**
             * grabar Auditoría
             */
            Object logObj = Aplinfo.cloneObjectEjb(objUser, false);
            String descripcion = "El usuario " + user.getApellidos() + " " + user.getNombres() + " inició una sesión en el sistema";

            grabarAuditoria(INICIAR_SESION, logObj, user, descripcion);
            /**
             * FIN -- grabar Auditoría
             */
            objUser.setFechaUltimoAcceso(getFechaDb());
            user.setSesion(token);

            getEntityManager().merge(objUser);
            return user;
        } catch (Exception e) {
            log.error("iniciarSesionToken({},...,...) {}", token, e.getMessage());
            throw new ApliException(TipoMensajeError.INICIAR_SESION, e);
        }
    }

    /**
     * Valida las credenciales para iniciar una sesión.
     *
     * @param sistema sistema desde el cual se inicia una sesión
     * @return el objeto usuario con todos los perfiles y datos
     * @throws Exception si existe un error
     */
    @Override
    public Object iniciarSesionBpm(AdmSesion token, String bpmId) throws Exception {
        if (token == null || token.getAdmSistema() == null) {
            throw new ApliException(TipoMensajeError.SYSTEM_NULL);
        }
        AdmUsuario objUser = null;
        try {
            objUser = (AdmUsuario) getEntityManager().createQuery("Select T from AdmUsuario T where T.username=:usr").setParameter("usr", token.getAdmUsuario().getUsername()).getSingleResult();
            if (objUser.getEstado() == 0) {
                throw new ApliException(TipoMensajeError.USER_INACTIVO);
            }
        } catch (ApliException e) {
            throw new ApliException(TipoMensajeError.USER_NO_REGISTERED, e);
        }
        UsuarioAdmin user = new UsuarioAdmin(objUser);
        // si es usuario del DA, recupero la clave para poder validar en el directorio activo
//        if (!user.isUsuarioExterno()) {
//            user.setClave2(UtilsSeguridad.desencripta(objUser.getPwd()));
//        }
        user.setBpmId(bpmId);
        user.setSistema(token.getAdmSistema());
        try {
            //Carga las acciones o permisos que tiene el usuario
            List<AdmAccion> o1 = getEntityManager().createQuery("Select distinct A.admAccionList from admUsuario T, in (T.admRolList) A where T = :u").setParameter("u", objUser).getResultList();
            Map<String, AdmAccion> permisos = new HashMap<>();

            for (AdmAccion admAccion : o1) {
                permisos.put(admAccion.getClave(), admAccion);
            }
            List<AdmMenu> menu = null;//getMenuPorSistemaAsignados(sistemaPrincipal != null ? sistemaPrincipal : sistema);
// --     
            user.setPermisosMap(permisos);
            menu = getListMenuPorPerfiles(menu, user);
            user.setMenu(menu);   /// utilizando el sistema

            user.setIp(token.getIp());
            // --             
            /**
             * grabar Auditoría
             */
            Object logObj = Aplinfo.cloneObjectEjb(objUser, false);
            String descripcion = "El usuario " + user.getApellidos() + " " + user.getNombres() + " inició una sesión en el sistema desde el BPM";

            grabarAuditoria(INICIAR_SESION, logObj, user, descripcion);
            /**
             * FIN -- grabar Auditoría
             */
//            objUser.setFechaUltimoAcceso(getFechaDb());
            user.setSesion(token);

//            getEntityManager().merge(objUser);
            return user;
        } catch (Exception e) {
            log.error("iniciarSesionBpm({},...,...) {}", token, e.getMessage());
            throw new ApliException(TipoMensajeError.INICIAR_SESION, e);
        }
    }
//--

    private List<AdmMenu> getListMenuPorPerfiles(List<AdmMenu> menu, UsuarioAdmin user) {
        if (menu == null) {
            return null;
        }
        List<AdmMenu> elementos = new ArrayList();
        try {
            for (AdmMenu obj : menu) {
                if (obj.getAdmMenuList() != null) {
                    obj.setAdmMenuList(getMenuPorPerfiles(obj, user));
                    if (obj.getAdmMenuList() != null && !obj.getAdmMenuList().isEmpty()) {
                        elementos.add(obj);
                    }
                } else {
                    if (obj.getObligatorio() == 0 && obj.getVisible() == 1) {
                        elementos.add(obj);
                    } else if (user != null && obj.getObligatorio() == 2) {
                        elementos.add(obj);
                    } else {
                        List<AdmAccion> listaAcciones = obj.getAdmAccionList();
                        for (AdmAccion ac : listaAcciones) {
                            if (obj.getVisible() == 1 && user.getPermisosMap() != null && user.getPermisosMap().containsKey(ac.getClave())) {
                                elementos.add(obj);
                                break;
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("getMenuPorPerfiles() {}", e.toString());
        }
        return elementos.isEmpty() ? null : elementos;
    }
//--

    private List<AdmMenu> getMenuPorPerfiles(AdmMenu menu, UsuarioAdmin user) {
        List<AdmMenu> elementos = new ArrayList();
        try {
            if (menu.getAdmMenuList() != null && !menu.getAdmMenuList().isEmpty()) {
                List<AdmMenu> datos = menu.getAdmMenuList();
                for (AdmMenu obj : datos) {
                    if (obj.getAdmMenuList() == null || obj.getAdmMenuList().isEmpty()) {
                        if (obj.getVisible() == 1 && obj.getObligatorio() == 0) {
                            elementos.add(obj);
                        } else if (obj.getVisible() == 1 && user != null && obj.getObligatorio() == 1) {
                            elementos.add(obj);
                        } else {
                            List<AdmAccion> listaAcciones = obj.getAdmAccionList();
                            for (AdmAccion ac : listaAcciones) {
                                if (obj.getVisible() == 1 && user != null && user.getPermisosMap() != null && user.getPermisosMap().containsKey(ac.getClave())) {
                                    elementos.add(obj);
                                    break;
                                }
                            }
                        }
                    } else {
                        obj.setAdmMenuList(getMenuPorPerfiles(obj, user));
                        if (obj.getVisible() == 1 && obj.getAdmMenuList() != null && !obj.getAdmMenuList().isEmpty()) {
                            elementos.add(obj);
                        }
                    }
                }
            } else {
                if (menu.getVisible() == 1 && menu.getObligatorio() == 0) {
                    elementos.add(menu);
                } else if (menu.getVisible() == 1 && user != null && menu.getObligatorio() == 1) {
                    elementos.add(menu);
                } else {
                    List<AdmAccion> listaAcciones = menu.getAdmAccionList();
                    for (AdmAccion ac : listaAcciones) {
                        if (menu.getVisible() == 1 && user.getPermisosMap() != null && user.getPermisosMap().containsKey(ac.getClave())) {
                            elementos.add(menu);
                            break;
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("getMenuPorPerfiles() {}", e.toString());
        }
        return elementos.isEmpty() ? null : elementos;
    }

    private List<AdmMenu> getSubMenu(AdmMenu menu, AdmSistema sistema, List<AdmMenu> menuPorAccion) {
        List<AdmMenu> elementos = new ArrayList();
        try {
            String sql = "SELECT COUNT(M) FROM AdmMenu M JOIN M.admSistemaList S  WHERE S = :v1 AND M.visible = :v2 AND M.admMenu =:v3";
            Long t = (Long) getEntityManager().createQuery(sql).setParameter("v1", sistema).setParameter("v2", Boolean.TRUE).setParameter("v3", menu).getSingleResult();
            if (t.intValue() < 1) { // no tiene menu
                return null;
            }
            //tiene elementos
            sql = "SELECT DISTINCT M FROM AdmMenu M JOIN M.admSistemaList S  WHERE S = :v1 AND M.visible = :v2 AND M.admMenu =:v3 ORDER BY M.secuencia";
            List<AdmMenu> datos = getEntityManager().createQuery(sql).setParameter("v1", sistema).setParameter("v2", Boolean.TRUE).setParameter("v3", menu).getResultList();
            for (AdmMenu oo : datos) {
                oo.setAdmMenuList(getSubMenu(oo, sistema, menuPorAccion));
                if (oo.getAdmMenuList() == null && oo.getObligatorio() == 2) {
                    if (menuPorAccion != null && menuPorAccion.contains(oo)) {
                        elementos.add(oo);
                    }
                } else {
                    elementos.add(oo);
                }
            }
        } catch (Exception e) {
            log.error("getSubMenu({}," + sistema.getNombre() + ") {}", menu.getNombre(), e.getMessage());
        }
        return elementos.isEmpty() ? null : elementos;
    }

    private List<AdmMenu> getMenu(AdmSistema sistema, List<AdmMenu> menuPorAccion) {
        List<AdmMenu> elementos = new ArrayList();
        try {
            String sql = "SELECT COUNT(T) FROM AdmMenu T JOIN T.admSistemaList S WHERE S = :v1 AND T.admMenu is null AND T.visible = :v2";
            Long t = (Long) getEntityManager().createQuery(sql).setParameter("v1", sistema).setParameter("v2", Boolean.TRUE).getSingleResult();
            if (t.intValue() < 1) { // no tiene menu
                return null;
            }
            //tiene elementos
            sql = "SELECT DISTINCT T FROM AdmMenu T JOIN T.admSistemaList S WHERE S = :v1 AND T.admMenu is null AND T.visible = :v2 ORDER BY T.secuencia";
            List<AdmMenu> datos = getEntityManager().createQuery(sql).setParameter("v1", sistema).setParameter("v2", Boolean.TRUE).getResultList();
            for (AdmMenu oo : datos) {
                oo.setAdmMenuList(getSubMenu(oo, sistema, menuPorAccion));
                if (oo.getAdmMenuList() == null && oo.getObligatorio() == 2) {
                    if (menuPorAccion != null && menuPorAccion.contains(oo)) {
                        elementos.add(oo);
                    }
                } else {
                    elementos.add(oo);
                }
            }
        } catch (Exception e) {
            log.error("getMenu({}) {}", sistema.getNombre(), e.getMessage());
        }
        return elementos.isEmpty() ? null : elementos;
    }

    /**
     *
     * @param obligatorio 0 = obtiene los menus sin iniciar sesión, 1 = obtiene
     * los menus cuando inicia una sesión
     * @return
     */
    private List<AdmMenu> getMenu(int obligatorio) {
        List<AdmMenu> elementos = new ArrayList();
        String sql = "SELECT T FROM AdmMenu T where T.admMenu is null and T.visible = 1 and T.obligatorio in (0) order by T.secuencia";
        try {
            if (obligatorio == 1) {
                sql = "SELECT T FROM AdmMenu T where T.admMenu is null and T.visible = 1 and T.obligatorio in (0,1) order by T.secuencia";
            }
            List<AdmMenu> datos = getEntityManager().createQuery(sql).getResultList();
            if (datos.size() < 1) { // no tiene menu
                return null;
            }
            //tiene elementos
//            sql = "SELECT DISTINCT T FROM AdmMenu T JOIN T.dmpSistemaList S WHERE S = :v1 AND T.dmpMenu is null AND T.visible = :v2 ORDER BY T.secuencia";
            //List<AdmMenu> datos = getEntityManager().createQuery(sql).setParameter("v1", sistema).setParameter("v2", Boolean.TRUE).getResultList();
            for (AdmMenu oo : datos) {
                oo.setAdmMenuList(getSubMenu(oo, obligatorio));
                if (oo.getAdmMenuList() == null) {
                    //if (menuPorAccion.contains(oo)) {
                    //elementos.add(oo);
                    //}
                } else {
                    elementos.add(oo);
                }
            }
        } catch (Exception e) {
            log.error("getMenu({}) {}", obligatorio, e.getMessage());
        }
        return elementos.isEmpty() ? null : elementos;
    }

    private List<AdmMenu> getSubMenu(AdmMenu menu, int obligatorio) {
        List<AdmMenu> elementos = new ArrayList();
        String sql = "SELECT T FROM AdmMenu T where T.admMenu = :v1 and T.visible = 1 and T.obligatorio in (0) order by T.secuencia";
        try {
            if (obligatorio == 1) {
                sql = "SELECT T FROM AdmMenu T where T.admMenu = :v1 and T.visible = 1 and T.obligatorio in (0,1) order by T.secuencia";
            }
            List<AdmMenu> datos = getEntityManager().createQuery(sql).setParameter("v1", menu).getResultList();
            if (datos.size() < 1) { // no tiene menu
                return null;
            }
            //tiene elementos
            //sql = "SELECT DISTINCT M FROM AdmMenu M JOIN M.dmpSistemaList S  WHERE S = :v1 AND M.visible = :v2 AND M.dmpMenu =:v3 ORDER BY M.secuencia";
            //List<AdmMenu> datos = getEntityManager().createQuery(sql).setParameter("v1", sistema).setParameter("v2", Boolean.TRUE).setParameter("v3", menu).getResultList();
            for (AdmMenu oo : datos) {
                oo.setAdmMenuList(getSubMenu(oo, obligatorio));
//                if (oo.getAdmMenuList() == null) {
//                    if (menuPorAccion.contains(oo)) {
//                        elementos.add(oo);
//                    }
//                } else {
                elementos.add(oo);
//                }
            }
        } catch (Exception e) {
            log.error("getSubMenu({}," + obligatorio + ") {}", menu.getNombre(), e.getMessage());
        }
        return elementos.isEmpty() ? null : elementos;
    }

    /**
     *
     * @param obligatorio 0 = obtiene los menus sin iniciar sesión, 1 = obtiene
     * los menus cuando inicia una sesión
     * @return
     */
    private List<AdmMenu> getMenu(AdmSistema sistema, int obligatorio) {
        List<AdmMenu> elementos = new ArrayList();
        String sql = "SELECT T FROM AdmMenu T where T.admMenu is null and T.visible = 1 and T.obligatorio in (0) and T.admSistema = :var1 order by T.secuencia";
        try {
            if (obligatorio == 1) {
                sql = "SELECT T FROM AdmMenu T where T.admMenu is null and T.visible = 1 and T.obligatorio in (0,1) and T.admSistema = :var1 order by T.secuencia";
            }
            List<AdmMenu> datos = getEntityManager().createQuery(sql).setParameter("var1", sistema).getResultList();
            if (datos.size() < 1) { // no tiene menu
                return null;
            }
            //tiene elementos
//            sql = "SELECT DISTINCT T FROM AdmMenu T JOIN T.dmpSistemaList S WHERE S = :v1 AND T.dmpMenu is null AND T.visible = :v2 ORDER BY T.secuencia";
            //List<AdmMenu> datos = getEntityManager().createQuery(sql).setParameter("v1", sistema).setParameter("v2", Boolean.TRUE).getResultList();
            for (AdmMenu oo : datos) {
                oo.setAdmMenuList(getSubMenu(oo, sistema, obligatorio));
                if (oo.getAdmMenuList() == null) {
                    //if (menuPorAccion.contains(oo)) {
                    //elementos.add(oo);
                    //}
                } else {
                    elementos.add(oo);
                }
            }
        } catch (Exception e) {
            log.error("getMenu({}) {}", obligatorio, e.getMessage());
        }
        return elementos.isEmpty() ? null : elementos;
    }

    private List<AdmMenu> getSubMenu(AdmMenu menu, AdmSistema sistema, int obligatorio) {
        List<AdmMenu> elementos = new ArrayList();
        String sql = "SELECT T FROM AdmMenu T where T.admMenu = :v1 and T.visible = 1 and T.obligatorio in (0) and T.admSistema = :var1 order by T.secuencia";
        try {
            if (obligatorio == 1) {
                sql = "SELECT T FROM AdmMenu T where T.admMenu = :v1 and T.visible = 1 and T.obligatorio in (0,1) and T.admSistema = :var1 order by T.secuencia";
            }
            List<AdmMenu> datos = getEntityManager().createQuery(sql).setParameter("v1", menu).setParameter("var1", sistema).getResultList();
            if (datos.size() < 1) { // no tiene menu
                return null;
            }
            //tiene elementos
            //sql = "SELECT DISTINCT M FROM AdmMenu M JOIN M.dmpSistemaList S  WHERE S = :v1 AND M.visible = :v2 AND M.dmpMenu =:v3 ORDER BY M.secuencia";
            //List<AdmMenu> datos = getEntityManager().createQuery(sql).setParameter("v1", sistema).setParameter("v2", Boolean.TRUE).setParameter("v3", menu).getResultList();
            for (AdmMenu oo : datos) {
                oo.setAdmMenuList(getSubMenu(oo, obligatorio));
//                if (oo.getAdmMenuList() == null) {
//                    if (menuPorAccion.contains(oo)) {
//                        elementos.add(oo);
//                    }
//                } else {
                elementos.add(oo);
//                }
            }
        } catch (Exception e) {
            log.error("getSubMenu({}," + obligatorio + ") {}", menu.getNombre(), e.getMessage());
        }
        return elementos.isEmpty() ? null : elementos;
    }

    @Override
    public List<AdmMenu> getMenu() {
        List<AdmMenu> elementos = new ArrayList();
        String sql = "SELECT T FROM AdmMenu T where T.admMenu is null and T.visible = 1 order by T.secuencia";
        try {
            List<AdmMenu> datos = getEntityManager().createQuery(sql).getResultList();
            if (datos.size() < 1) { // no tiene menu
                return null;
            }
            //tiene elementos
//            sql = "SELECT DISTINCT T FROM AdmMenu T JOIN T.dmpSistemaList S WHERE S = :v1 AND T.dmpMenu is null AND T.visible = :v2 ORDER BY T.secuencia";
            //List<AdmMenu> datos = getEntityManager().createQuery(sql).setParameter("v1", sistema).setParameter("v2", Boolean.TRUE).getResultList();
            for (AdmMenu oo : datos) {
                oo.setAdmMenuList(getSubMenu(oo));
                if (oo.getAdmMenuList() == null) {
                    //if (menuPorAccion.contains(oo)) {
                    //elementos.add(oo);
                    //}
                } else {
                    elementos.add(oo);
                }
            }
        } catch (Exception e) {
            log.error("getMenu() {}", e.getMessage());
        }
        return elementos.isEmpty() ? null : elementos;
    }

    private List<AdmMenu> getSubMenu(AdmMenu menu) {
        List<AdmMenu> elementos = new ArrayList();
        String sql = "SELECT T FROM AdmMenu T where T.admMenu = :v1 and T.visible = 1 order by T.secuencia";
        try {
            List<AdmMenu> datos = getEntityManager().createQuery(sql).setParameter("v1", menu).getResultList();
            if (datos.size() < 1) { // no tiene menu
                return null;
            }
            //tiene elementos
            //sql = "SELECT DISTINCT M FROM AdmMenu M JOIN M.dmpSistemaList S  WHERE S = :v1 AND M.visible = :v2 AND M.dmpMenu =:v3 ORDER BY M.secuencia";
            //List<AdmMenu> datos = getEntityManager().createQuery(sql).setParameter("v1", sistema).setParameter("v2", Boolean.TRUE).setParameter("v3", menu).getResultList();
            for (AdmMenu oo : datos) {
                oo.setAdmMenuList(getSubMenu(oo));
//                if (oo.getAdmMenuList() == null) {
//                    if (menuPorAccion.contains(oo)) {
//                        elementos.add(oo);
//                    }
//                } else {
                elementos.add(oo);
//                }
            }
        } catch (Exception e) {
            log.error("getSubMenu({}) {}", menu.getNombre(), e.getMessage());
        }
        return elementos.isEmpty() ? null : elementos;
    }

//    @Override
//    public ApliUsuario iniciarSesion(String username, String password, String ip, String host) throws Exception {
//        throw new UnsupportedOperationException("Not supported yet.");
//    }
//
//    @Override
//    public void reestablecerPassword(ApliUsuario userReset, ApliUsuario user) {
//        throw new UnsupportedOperationException("Not supported yet.");
//    }
    @Override
    public List<AdmMenu> getMenuPorSistemaAsignados(AdmSistema sistema) throws Exception {
        if (sistema == null) {
            return null;
        }
        List<AdmMenu> elementos = null;
        Map<String, AdmMenu> datosMenus = new HashMap<>();
        String sql = "SELECT T FROM AdmMenu T where T.admMenu is null  order by T.secuencia";
        try {
            AdmSistema sis = (AdmSistema) (Object) buscar(AdmSistema.class, sistema.getIdSistema());
            elementos = sis.getAdmMenuList();
            for (AdmMenu obj : elementos) {
                datosMenus.put(obj.getClave(), obj);
            }
            elementos = new ArrayList<>();
            List<AdmMenu> datos = getEntityManager().createQuery(sql).getResultList();
            if (datos.size() < 1) { // no tiene menu
                return null;
            }
            for (AdmMenu oo : datos) {
                if (!datosMenus.containsKey(oo.getClave())) {
                    continue;
                }
                oo.setAdmMenuList(getSubMenuPorSistemaAsignados(oo, datosMenus));
                if (oo.getAdmMenuList() != null) {
                    elementos.add(oo);
                }
            }
        } catch (Exception e) {
            log.error("getMenu() {}", e.getMessage());
        }
        return elementos.isEmpty() ? null : elementos;
    }

    private List<AdmMenu> getSubMenuPorSistemaAsignados(AdmMenu menu, Map<String, AdmMenu> menusUsuario) {
        List<AdmMenu> elementos = new ArrayList();
        String sql = "SELECT T FROM AdmMenu T where T.admMenu = :v1  order by T.secuencia";
        try {
            List<AdmMenu> datos = getEntityManager().createQuery(sql).setParameter("v1", menu).getResultList();
            if (datos.size() < 1) { // no tiene menu
                return null;
            }
            for (AdmMenu oo : datos) {
                if (!menusUsuario.containsKey(oo.getClave())) {
                    continue;
                }
                oo.setAdmMenuList(getSubMenuPorSistemaAsignados(oo, menusUsuario));
                elementos.add(oo);
            }
        } catch (Exception e) {
            log.error("getSubMenu({}) {}", menu.getNombre(), e.getMessage());
        }
        return elementos.isEmpty() ? null : elementos;
    }

    @Override
    public List<AdmMenu> getMenusPorSistemaNoAsignados(AdmSistema sistema) throws Exception {
        if (sistema == null) {
            return null;
        }
        List<AdmMenu> elementos = null;
        Map<String, AdmMenu> datosMenus = new HashMap<>();
        String sql = "SELECT T FROM AdmMenu T ";// order by T.secuencia";
        String claves = "";
        try {
            AdmSistema sis = (AdmSistema) (Object) buscar(AdmSistema.class, sistema.getIdSistema());
            elementos = sis.getAdmMenuList();

            for (AdmMenu obj : elementos) {
//                datosMenus.put(obj.getClave(), obj);
                claves += "'" + obj.getClave() + "' ,";
            }
            if (claves.length() > 0) {
                claves = claves.substring(0, claves.length() - 1);
            }
            if (claves.length() > 0) {
                sql = sql + " where T.clave not in (" + claves + ")  order by T.secuencia";
            } else {
                sql = sql + " order by T.secuencia";
            }
            List<AdmMenu> datos = getEntityManager().createQuery(sql).getResultList();
            for (AdmMenu obj : datos) {
                agregarMenu(obj, datosMenus);
                //       datosMenus.put(obj.getClave(), obj);
                //              claves += obj.getClave() + " ,";
            }
            elementos = new ArrayList<>();
//            if (obligatorio == 1) {
//                sql = "SELECT T FROM AdmMenu T where T.dmpMenu is null and T.visible = 1 and T.obligatorio in (0,1) and T.dmpSistema = :var1 order by T.secuencia";
//            }
            sql = "SELECT T FROM AdmMenu T where T.admMenu is null  order by T.secuencia";
            datos = getEntityManager().createQuery(sql).getResultList();
            if (datos.size() < 1) { // no tiene menu
                return null;
            }
            //tiene elementos
//            sql = "SELECT DISTINCT T FROM AdmMenu T JOIN T.dmpSistemaList S WHERE S = :v1 AND T.dmpMenu is null AND T.visible = :v2 ORDER BY T.secuencia";
            //List<AdmMenu> datos = getEntityManager().createQuery(sql).setParameter("v1", sistema).setParameter("v2", Boolean.TRUE).getResultList();
            for (AdmMenu oo : datos) {
                if (!datosMenus.containsKey(oo.getClave())) {
                    continue;
                }
                oo.setAdmMenuList(getSubMenuPorSistemaAsignados(oo, datosMenus));
                if (oo.getAdmMenuList() == null) {
                    //if (menuPorAccion.contains(oo)) {
                    //elementos.add(oo);
                    //}
                } else {
                    elementos.add(oo);
                }
            }
        } catch (Exception e) {
            log.error("getMenu() {}", e.getMessage());
        }
        return elementos.isEmpty() ? null : elementos;
    }

    private void agregarMenu(AdmMenu obj, Map<String, AdmMenu> datosMenus) {
        if (obj != null) {
            datosMenus.put(obj.getClave(), obj);
        }
        if (obj.getAdmMenu() != null) {
            agregarMenu(obj.getAdmMenu(), datosMenus);
        }
    }
//
//    @Override
//    public void registrarLicencia(String[] datos) throws Exception {
//        try {
//            if (datos == null || datos.length != 3) {
//                throw new Exception("Valor incorrecto");
//            }
//            Object mm = listarContiene(AdmDatosGlobales.class, "clave", "muni.lic");
//            List<AdmDatosGlobales> dd = (List<AdmDatosGlobales>) mm;
//            for (AdmDatosGlobales obj : dd) {
//                getEntityManager().remove(obj);
//            }
//            for (int i = 0; i < 3; i++) {
//                AdmDatosGlobales d = new AdmDatosGlobales();
//                d.setDmpDatosGloba((Integer) getNuevoCodigo(AdmDatosGlobales.class));
//                d.setClave("muni.lic" + i);
//                d.setValor(datos[i]);
//                getEntityManager().persist(d);
//            }
//        } catch (Exception e) {
//            log.error("registrarLicencia() {}", e.getMessage());
//        }
//    }
//
//    @Override
//    public String[] obtenerLicencia() throws Exception {
//        String[] datos = new String[3];
//        try {
//            Object mm = listarContiene(AdmDatosGlobales.class, "clave", "muni.lic");
//            List<AdmDatosGlobales> dd = (List<AdmDatosGlobales>) mm;
//            if (dd.size() != 3) {
//                throw new Exception("Datos incorrectos");
//            }
//            for (AdmDatosGlobales obj : dd) {
//                if (obj.getClave().equals("muni.lic0")) {
//                    datos[0] = obj.getValor();
//                } else if (obj.getClave().equals("muni.lic1")) {
//                    datos[1] = obj.getValor();
//                } else if (obj.getClave().equals("muni.lic2")) {
//                    datos[2] = obj.getValor();
//                }
//            }
//
//            String lic0 = datos[0];
//            String lic1 = datos[1];
//            String lic2 = datos[2];
//            lic0 = UtilsSeguridad.desencripta(lic0);
//            lic1 = UtilsSeguridad.desencripta(lic1);
//            lic2 = UtilsSeguridad.desencripta(lic2);
//            if (!lic2.startsWith(lic0) || !lic2.endsWith(lic1)) {
//                throw new Exception("Clave de activación no válida");
//            }
//            lic2 = lic2.substring(UtilsSeguridad.desencripta(lic0).length());
//            lic2 = lic2.substring(0, lic2.length() - lic1.length());
//            lic2 = UtilsSeguridad.desencripta(lic2);
//
//            datos[0] = lic0;
//            datos[1] = lic1;
//            datos[2] = lic2;
//        } catch (Exception e) {
//            log.error("obtenerLicencia() {}", e.getMessage());
//        }
//        return datos;
//    }

    @Override
    public AdmSesion getSesion(String sesion) throws Exception {
        try {
            Object mm = buscar(AdmSesion.class, "sesion", sesion);
            if (mm == null) {
                return null;
            }
            return (AdmSesion) mm;
        } catch (Exception e) {
            log.error("getSesion() {}", e.getMessage());
        }
        return null;
    }
//--

    @Override
    public List<AdmMenu> getMenuBase(AdmSistema sistema) throws Exception {
        try {
            List<AdmMenu> menu = getMenuPorSistemaAsignados(sistema);
            menu = getListMenuPorPerfiles(menu, null);
            return menu;
        } catch (Exception e) {
            log.error("getMenuBase() {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public Object iniciarSesion(String string, String string1, String string2, String string3) throws Exception {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void reestablecerPassword(Object o, Object o1) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean existeUsuarioAD(String username, Object user) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public UsuarioAdmin getUsuario(String username, UsuarioAdmin usuario) throws Exception {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean isUsuarioAD(String username, String password) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
